<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="root"></div>
    <script>
        // requestIdleCallback的使用
        requestIdleCallback((time) => { // 参数time就是deadline
            console.log(time.timeRemaining(), time.didTimeout);
            /*
                deadline有两个值
                    timeRemaining()：返回是否还有空闲时间，单位是毫秒
                    didTimeout：是否因为超时被强制执行，跟配置的第二参数有关，如果配置了timeout，则超过时间后，会强制执行回调函数，此时didTimeout为true，否则为false
            */
        }, { timeout: 2000 })

        // 使用场景，如果要求网页一下渲染20000个dom,直接渲染会导致页面卡死，此时可以使用requestIdleCallback，将渲染任务拆分成多个小任务，在空闲时间执行
        const total = 20000;
        const arr = []
        function generateArr() {
            for (let i = 0; i < total; i++) {
                arr.push(() => {
                    document.getElementById('root').innerHTML += `<div>${i}</div>`
                })
            }
        }
        generateArr()

        // for (let i = 0; i < total; i++) {
        //     arr[i]() // 直接渲染会导致页面卡死,阻塞主线程
        // }

        function workloop(deadline) {
            while (deadline.timeRemaining() > 1 && arr.length > 0) {
                arr.shift()()
            }
            if (arr.length > 0) {
                requestIdleCallback(workloop)
            }
        }

        requestIdleCallback(workloop)


        // react没有用原生的requestIdleCallback，而是自己实现了一个
        // 因为requestIdleCallback兼容性不好
        // 每一帧的操作，基本是在宏任务中做的，所以react基于setTimeout实现了自己的requestIdleCallback
        // 但实际上，setTimeout嵌套会有强制空出时间，会浪费4毫秒，所以react是基于MessageChannel实现了一个，但当有的浏览器不支持MessageChannel时，会降级使用setTimeout
        // MessageChannel是H5新增的API，用于创建一个新的消息通道，通过postMessage方法发送消息，onmessage方法接收消息，是js多线程通信用的，比如 web workr或 iframe 和主线程的通信
        // MessageChannel是发布订阅的方式
        const channel = new MessageChannel()
        // 就是port1和port2是两个端口，一个发送消息，一个接收消息
        // 接收消息
        channel.port1.onmessage = (event) => {
            console.log('message');
            console.log(event.data);
        }
        // 发送消息
        channel.port2.postMessage('hello')

    </script>
    <script src="./scheduler.js"></script>
</body>
</html>